package futbol.tacticas.concursantes2007.NadaEsImposible;

import futbol.tacticas.*;
import futbol.General;
import futbol.tacticas.concursantes.Tactica;

import java.awt.Color;
import java.awt.Point;
import java.util.Vector;
import java.util.Random;

public class TacticaYerlie implements Tactica{
    
    //########################################################################################
    
    private Random rand=new Random();
    
    //########################################################################################
    
    public String getNombre(){
        return "NadaEsImposible";
    }
    public Color getColor1(){
        return Color.BLACK;
    }
    public Color getColor2(){
        return Color.RED;
    }
    public Color getColorNumero(){
        return Color.WHITE;
    }
    public int getFuerza(int n){
        speeds[n][0]=10-matriz[n][2];
        return matriz[n][2];
    }
    public int getXInicial(int n){
        return matriz[n][0];
    }
    public int getYInicial(int n){
        return matriz[n][1];
    }
    
    //########################################################################################
    //matriz de posiciones iniciales y fuerza
    private int matriz[][]={
        {-152,0,7},
        {-100,100,7},
        {-120,30,7},
        {-120,-30,7},
        {-100,-100,7},
        {20,100,7},
        {-20,30,7},
        {-20,-30,7},
        {20,-100,7},
        {120,30,7},
        {100,-60,7}
    };
    //matriz de velocidades de los jugadores
    private int speeds[][]={
        {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
    //situacion actual
    private SituacionJugadores sj=null;
    //situacion anterior
    private SituacionJugadores sj0=null;
    //indica el marcador
    private int goles[]=new int[2];
    //indica cuando un jugador esta en posicion de chutar
    private boolean[][] puedeChutar=new boolean[11][2];
    //posicion de la pelota
    private Point bola;
    //posicion anterior de mis jugadores
    private Point bola0;
    //posicion de mis jugadores
    private Point[] misJugadores;
    //posicion anterior de mis jugadores
    private Point[] misJugadores0;
    //posicion de los contrarios
    private Point[] contrarios;
    //posicion anterior de los contrarios
    private Point[] contrarios0;
    
    //########################################################################################
    private int count=0;
    private void capturarInformacion(){
        int i;
        count++;
        
        bola=sj.getBola();
        misJugadores=sj.getMisJugadores();
        contrarios=sj.getContrario();
        
        //puedeChutar
        for(i=0;i<11;i++){
            puedeChutar[i][0]=General.getDistancia(misJugadores[i].x,misJugadores[i].y,bola.x,bola.y)<10;
            puedeChutar[i][1]=General.getDistancia(contrarios[i].x,contrarios[i].y,bola.x,bola.y)<10;
        }
        
        if (sj0!=null){
            bola0=sj0.getBola();
            misJugadores0=sj0.getMisJugadores();
            contrarios0=sj0.getContrario();
            
            //GOL!!!!!
            boolean gol=false;
            if (bola.x==0 && bola.y==0 && bola0.x<=-159){
                goles[1]++;
                gol=true;
            }
            if (bola.x==0 && bola.y==0 && bola0.x>=159){
                goles[0]++;
                gol=true;
            }
            
            if (!gol) {
                contrarios0=sj0.getContrario();
                for(i=0;i<11;i++){
                    if (speeds[i][1]==-1 && !contrarios0[i].equals(contrarios[i])){
                        speeds[i][1]=
                                Math.round((float)Math.sqrt(
                                (contrarios0[i].x-contrarios[i].x)*(contrarios0[i].x-contrarios[i].x)
                                +(contrarios0[i].y-contrarios[i].y)*(contrarios0[i].y-contrarios[i].y)));
                    }
                }
            }
        }
        //guarda la situacion anterior
        sj0=sj;
        getPuntosOptimos();
    }
    
    Point[][] puntosOptimos=new Point[11][2];
    double[][] pasos=new double[11][2];
    private void getPuntosOptimos(){
        int i,j;
        if (bola0==null){
            for(i=0;i<11;i++)
                for(j=0;j<2;j++)
                    puntosOptimos[i][j]=bola;
        } else {
            int velocidad=(int)General.getDistancia(bola0.x,bola0.y,bola.x,bola.y);
            if (velocidad==0){
                for(i=0;i<11;i++)
                    for(j=0;j<2;j++)
                        puntosOptimos[i][j]=bola;
            } else {
                double angulo=General.getAngulo(bola0.x,bola0.y,bola.x,bola.y);
                double dx=Math.cos(angulo);
                double dy=Math.sin(angulo);
                int k;
                Point[] trayectoria=new Point[velocidad+1];
                trayectoria[velocidad]=bola;
                for(k=velocidad-1;k>=0;k--)
                    trayectoria[k]=new Point((int)(trayectoria[k+1].x+dx*k),(int)(trayectoria[k+1].y+dy*k));//falta implementar el rebote en los muros...
                Point p;
                double x,y;
                double speed;
                for(i=0;i<11;i++){
                    for(j=0;j<2;j++){
                        if (j==0){
                            p=misJugadores[i];
                            speed=speeds[i][0]+increment;
                        } else{
                            p=contrarios[i];
                            if (speeds[i][1]==-1)
                                speed=5;
                            else
                                speed=speeds[i][1];
                        }
                        puntosOptimos[i][j]=null;
                        int min=velocidad-1;
                        if (min>14)
                            min=14;
                        for(k=min;k>=0;k--){
                            angulo=General.getAngulo(p.x,p.y,trayectoria[k].x,trayectoria[k].y);
                            x=p.x+Math.cos(angulo)*speed*(velocidad-k);
                            y=p.y+Math.sin(angulo)*speed*(velocidad-k);
                            if (General.getDistancia(trayectoria[k].x,trayectoria[k].y,x,y)<=4.5){
                                puntosOptimos[i][j]=trayectoria[k];
                                break;
                            }
                        }                        
                        if (puntosOptimos[i][j]==null)
                            puntosOptimos[i][j]=trayectoria[0];                        
                    }
                }
            }
        }
        Point p;
        double speed;
        for(i=0;i<11;i++){
            for(j=0;j<2;j++){
                if (j==0){
                    p=misJugadores[i];
                    speed=speeds[i][0]+increment;
                } else{
                    p=contrarios[i];
                    speed=speeds[i][1];
                }
                pasos[i][j]=General.getDistancia(puntosOptimos[i][j].x,puntosOptimos[i][j].y,p.x,p.y)/speed;
            }
        }
    }
    
//########################################################################################
//comando ir a mejorado
    public double increment=4.0;//valores de 0 a 3.5
    private ComandoIrA newIrA(int nJug,int x,int y){
        if (misJugadores==null)
            return new ComandoIrA(nJug,x,y);
        if (increment==0)
            return new ComandoIrA(nJug,x,y);
        double dist=General.getDistancia(misJugadores[nJug].x,misJugadores[nJug].y,x,y);
        double newSpeed=((double)speeds[nJug][1]+increment);
        if (dist>newSpeed){
            double ang=General.getAngulo(misJugadores[nJug].x,misJugadores[nJug].y,x,y);
            double dx=Math.cos(ang)*(double)newSpeed;
            double dy=Math.sin(ang)*(double)newSpeed;
            return new ComandoIrA(nJug,misJugadores[nJug].x+(int)dx,misJugadores[nJug].y+(int)dy);
        } else
            return new ComandoIrA(nJug,x,y);
    }
//########################################################################################
//comando ir a mejorado
    public Comando newGolpearBola(int nJug,int x,int y){
        return null;
    }
    
//########################################################################################
    Vector<Comando> com=new Vector();
//########################################################################################
    private void posicionInicial(){
        for (int n=0;n<11;n++)
            com.add(newIrA(n, getXInicial(n), getYInicial(n)));
    }
//########################################################################################
    private void mejorarDefensa(){
        if (!sj.estoyMasCercaDeBola() || bola.getX()<0){
            int nJC=sj.getContrarioMasCerca(getXInicial(5), getYInicial(5));
            com.add(newIrA(5, (int)(contrarios[nJC].getX()+bola.x)/2, (int)(contrarios[nJC].getY()+bola.y)/2));
        }
    }
//########################################################################################
    private int seguirLaBola(int jugadores){
        double max[]=new double[jugadores];
        int idx[]=new int[jugadores];
        for(int k=0;k<jugadores;k++){
            max[k]=1000;
            idx[k]=-1;
            boolean ok;
            for(int i=0;i<11;i++){
                ok=true;
                for(int m=0;m<k;m++){
                    if (i==idx[m]){
                        ok=false;
                        break;
                    }
                }
                if (ok && pasos[i][0]<max[k]){
                    max[k]=pasos[i][0];
                    idx[k]=i;
                }
            }
            if (idx[k]>-1)
                com.add(newIrA(idx[k],puntosOptimos[idx[k]][0].x,puntosOptimos[idx[k]][0].y));
        }
        return 0;
    }
//########################################################################################
    private void movimientoPortero(){
        int y=(int)(bola.getY()/2);
        if (y<-25) y=-25;
        if (y>25) y=25;
        com.add(newIrA(0,matriz[0][0], y));
        com.add(newIrA(1,matriz[1][0], y-10));
        com.add(newIrA(2,matriz[2][0], y+10));
        com.add(newIrA(3,matriz[3][0], y-20));
        com.add(newIrA(4,matriz[4][0], y+20));
    }
//########################################################################################
    public Vector<Comando> getComandos(SituacionJugadores sj){
        com.clear();
        this.sj=sj;
        capturarInformacion();
        posicionInicial();
        //mejorarDefensa();
        seguirLaBola(5);
        for(int i=0;i<11;i++)
            com.add(new ComandoTiroAPuerta(i,0));
        //movimientoPortero();
        
        return com;
    }
//########################################################################################
    
    
}
